/*
 * flash.c
 *
 *  Created on: 2017骞�7鏈�20鏃�
 *      Author: 4337
 */
#include "S32K144_features.h"

#include "includes.h"
/* Function declarations */
void FTFC_IRQHandler(void);
/* If target is flash, insert this macro to locate callback function into RAM */
START_FUNCTION_DECLARATION_RAMSECTION
void CCIF_Callback(void)
END_FUNCTION_DECLARATION_RAMSECTION

status_t ret;
flash_callback_t pCallBack;
//flash_command_sequence_t pCmdSequence;

flash_ssd_config_t flashSSDConfig;
const flash_user_config_t Flash_InitConfig0 = {
	.PFlashBase  = 0x00000000U,
    .PFlashSize  = 0x00100000U,
    .DFlashBase  = 0x10000000U,
    .EERAMBase   = 0x14000000U,
    .CallBack    = NULL_CALLBACK
};

uint8 EepromInit(void)
{

	status_t ret;
	flash_callback_t pCallBack;
	uint8_t timeout=0;
#if 0
	CLEAR_FTFx_FSTAT_ERROR_BITS;
	if ((FTFC->FCNFG & FTFC_FCNFG_EEERDY_MASK) == 0U)
	{
		//volatile int timeout;
		FTFC->FCCOB[3]=0x80; // Program Partition command
		FTFC->FCCOB[2]=0x00; // CSEc key size
		FTFC->FCCOB[1]=0x00; // Security flag extension - User Key verify only disabled
		FTFC->FCCOB[0]=0x00; // Load data int EEERAM in reset sequence
		FTFC->FCCOB[7]=0x02; // EEPROM data set size code - 4k
		FTFC->FCCOB[6]=0x03; // EEPROM backup size - 32k
		FTFC->FSTAT |=  FTFC_FSTAT_CCIF_MASK;

		while (((FTFC->FSTAT & FTFC_FSTAT_CCIF_MASK) == 0U)&&(timeout<100))
		{
			timeout++;
		}
	}
#endif

#if 1

#ifdef S32K146_SERIES
    MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM1(0xFu);
    MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM1(0xFu);
    MSCM->OCMDR[2u] |= MSCM_OCMDR_OCM1(0xFu);
#endif /* S32K144_SERIES */

    /* Always initialize the driver before calling other functions */
    //ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
    //DEV_ASSERT(STATUS_SUCCESS == ret);


#if ((FEATURE_FLS_HAS_FLEX_NVM == 1u) & (FEATURE_FLS_HAS_FLEX_RAM == 1u))
    /* Config FlexRAM as EEPROM if it is currently used as traditional RAM */
    flashSSDConfig.EEESize=0;
    if (flashSSDConfig.EEESize == 0u)
    {
        /* Configure FlexRAM as EEPROM and FlexNVM as EEPROM backup region,
         * DEFlashPartition will be failed if the IFR region isn't blank.
         * Refer to the device document for valid EEPROM Data Size Code
         * and FlexNVM Partition Code. For example on S32K144:
         * - EEEDataSizeCode = 0x02u: EEPROM size = 4 Kbytes
         * - DEPartitionCode = 0x08u: EEPROM backup size = 64 Kbytes
    	 * - DEPartitionCode = 0x03u: EEPROM backup size = 32 Kbytes */
    	ret = FLASH_DRV_DEFlashPartition(&flashSSDConfig, 0x02u, 0x03u, 0x0u, false);// true);
        DEV_ASSERT(STATUS_SUCCESS == ret);

        /* Re-initialize the driver to update the new EEPROM configuration */
        ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
        DEV_ASSERT(STATUS_SUCCESS == ret);

        /* Make FlexRAM available for EEPROM */
        ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
        DEV_ASSERT(STATUS_SUCCESS == ret);
    }
    else    /* FLexRAM is already configured as EEPROM */
    {
        /* Make FlexRAM available for EEPROM, make sure that FlexNVM and FlexRAM
         * are already partitioned successfully before */
        ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);
        DEV_ASSERT(STATUS_SUCCESS == ret);
    }
#endif /* (FEATURE_FLS_HAS_FLEX_NVM == 1u) & (FEATURE_FLS_HAS_FLEX_RAM == 1u) */

	return ret;
#endif
}

void flash_init(void)
{
#if 0
	MSCM->OCMDR[0u] |= MSCM_OCMDR_OCM0(0xFu) | MSCM_OCMDR_OCM1(0xFu) | MSCM_OCMDR_OCM2(0xFu);
    MSCM->OCMDR[1u] |= MSCM_OCMDR_OCM0(0xFu) | MSCM_OCMDR_OCM1(0xFu) | MSCM_OCMDR_OCM2(0xFu);
    MSCM->OCMDR[2u] |= MSCM_OCMDR_OCM0(0xFu) | MSCM_OCMDR_OCM1(0xFu) | MSCM_OCMDR_OCM2(0xFu);
    MSCM->OCMDR[3u] |= MSCM_OCMDR_OCM0(0xFu) | MSCM_OCMDR_OCM1(0xFu) | MSCM_OCMDR_OCM2(0xFu);
#endif
	//ret = FLASH_DRV_Init(&Flash_InitConfig0, &flashSSDConfig);
    EepromInit();
}

status_t flash_erase_sector(uint32_t addr,uint32_t size)
{
	status_t ret;
	ret = FLASH_DRV_EraseSector(&flashSSDConfig, addr, size);
	if (ret != STATUS_SUCCESS)
	{
		//while(1);
	}
	return ret;
}

status_t flash_program_data(uint32_t addr, uint8_t *pdata, uint32_t byte_size)
{
	status_t ret;
	/* Disable Callback */
	flashSSDConfig.CallBack = NULL_CALLBACK;
	ret = FLASH_DRV_Program(&flashSSDConfig, addr, byte_size, pdata);
	if(ret != STATUS_SUCCESS)
	{
		//while(1);
	}
	return ret;
}

status_t _erase_image(uint32_t addr)
{
	status_t ret = 0;

    if(addr>=Flash_InitConfig0.DFlashBase)
    {
    	if((addr & (FEATURE_FLS_DF_BLOCK_SECTOR_SIZE-1))==0)
		{
    		ret = flash_erase_sector(addr,FEATURE_FLS_DF_BLOCK_SECTOR_SIZE);
		}
    }
    else
    {
    	if((addr & (FEATURE_FLS_PF_BLOCK_SECTOR_SIZE-1))==0)
		{
    		DISABLE_INTERRUPTS();
    		ret = flash_erase_sector(addr,FEATURE_FLS_PF_BLOCK_SECTOR_SIZE);
    		ENABLE_INTERRUPTS();
		}
    }
    return ret;
}

status_t _write_image(uint8_t * data, uint16_t data_size, uint32_t addr)
{
	status_t ret;
	uint8_t i;
    static uint8_t abuf[128];
    DISABLE_INTERRUPTS();

    for(i = 0; i < data_size; i++)
    {
    	abuf[i] = data[i];
    }
    ret = flash_program_data(addr, abuf, data_size);
    ENABLE_INTERRUPTS();

    return ret;
}

void FTFC_IRQHandler(void)
{
    /* Disable Flash Command Complete interrupt */
    FTFx_FCNFG &= (~FTFx_FCNFG_CCIE_MASK);

    return;
}

/*!
  \brief Callback function for Flash operations
*/
START_FUNCTION_DEFINITION_RAMSECTION
void CCIF_Callback(void)
{
    /* Enable interrupt for Flash Command Complete */
    if ((FTFx_FCNFG & FTFx_FCNFG_CCIE_MASK) == 0u)
    {
        FTFx_FCNFG |= FTFx_FCNFG_CCIE_MASK;
    }
}
END_FUNCTION_DEFINITION_RAMSECTION

static void ByteRead(uint32_t addr, uint32_t *dat)
{
	*dat = *((uint32_t *)(addr));
}

void flash_read(uint32_t start,uint8_t *dat,uint16_t size)
{
	uint8_t i;
	uint32_t data;
	DISABLE_INTERRUPTS();

	for(i = 0; i< size;i++)
	{
		ByteRead(start,&data);
		dat[i++] = (uint8_t)data;
		dat[i++] = (uint8_t)(data>>8);
		dat[i++] = (uint8_t)(data>>16);
		dat[i]   = (uint8_t)(data>>24);
		start= start + 4;
	}
	ENABLE_INTERRUPTS();
}


uint8_t DFlash_ByteRead(uint32_t addr)
{
	uint8_t data;

	data=*(uint8_t *)(addr);

	return data;
}


void Read_Block_2Words(uint32_t FirstAddr,uint16_t *dat,uint16_t size)
{
	uint8_t i;
	uint32_t data;
	DISABLE_INTERRUPTS();

	for(i = 0; i< size;i++)
	{
		ByteRead(FirstAddr,&data);
		dat[i++] = (uint16_t)data;
		dat[i] =(uint16_t)(data>>16);
		FirstAddr = FirstAddr + 4;
	}
	ENABLE_INTERRUPTS();
}

uint8_t EepromWrite(MemM_MemDrvParam *drvPar)
{
	status_t ret;

	uint32_t address = drvPar->memAddr;
	uint32_t size = drvPar->memSize;
	uint8_t* pData = drvPar->memDataBuf;

	ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, size, pData);
    return ret;

}

uint8_t EEP_Write(MemM_MemDrvParam* drvPar)
{
	uint8  lRetVal = E_NOT_OK;
	lRetVal = EepromWrite(drvPar);
	return(lRetVal);
}

uint8_t EEP_Read(MemM_MemDrvParam *drvPar)
{
	uint16_t i;
	uint32_t address = drvPar->memAddr;
	uint32_t size = drvPar->memSize;
	uint8_t* pData = drvPar->memDataBuf;

	for(i = 0;i < size;i++)
	{
		*pData = *((uint8_t *)address);
		 pData++;
		 address++;
	}
	return 0;
}
